package com.cqndt.disaster.device.user;

import com.cqndt.disaster.device.common.shrio.ShiroUtils;
import com.cqndt.disaster.device.common.util.Constant;
import com.cqndt.disaster.device.common.util.RASUtils;
import com.cqndt.disaster.device.common.util.Result;
import com.cqndt.disaster.device.domain.TabLoginLog;
import com.cqndt.disaster.device.domain.TabMapservice;
import com.cqndt.disaster.device.domain.TabUser;
import com.cqndt.disaster.device.user.service.TabLoginService;
import com.cqndt.disaster.device.user.service.TabMapService;
import com.cqndt.disaster.device.vo.TabUserVo;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import com.ut.uttools.service.LoginService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created By marc
 * Date: 2019/4/4  11:21
 * Description:登录
 */
@RestController
@RequestMapping("/login")
@Api(value = "用户登陆", description = "用户登陆")
public class LoginController {
    @Autowired
    private Producer producer;
    @Autowired
    private TabMapService tabMapService;
    @Autowired
    private TabLoginService tabLoginService;

    @GetMapping("getCaptcha")
    @ApiOperation(value = "获取验证码", notes = "获取验证码")
    public void captcha(HttpServletResponse response)throws IOException {
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");
        //生成文字验证码
        String text = producer.createText();
        //生成图片验证码
        BufferedImage image = producer.createImage(text);
        //保存到shiro session
        ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text);
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
    }

    @GetMapping("checkCaptcha")
    @ApiOperation(value = "验证验证码", notes = "验证验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "code", value = "验证码", defaultValue = "", required = true, paramType = "query")
    })
    public Result checkCaptcha(String code){
        try{
            String kaptcha = ShiroUtils.getKaptcha(Constants.KAPTCHA_SESSION_KEY);
            if(!kaptcha.equalsIgnoreCase(code)){
                return new Result().failure(-1,"验证码错误");
            }
        }catch(Exception e){
            return new Result().failure(-1,e.getMessage());
        }
        return new Result().success();
    }

    /**
     * 登录
     */
    @PostMapping("login")
    @ApiOperation(value = "登录", notes = "登录")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "userName", value = "用户名", defaultValue = "", required = true, paramType = "query"),
            @ApiImplicitParam(dataType = "String", name = "password", value = "密码", defaultValue = "", required = true, paramType = "query")
    })
    public Result login(HttpServletRequest request, String userName, String password,String code){
        try {
            String kaptcha = ShiroUtils.getKaptcha(Constants.KAPTCHA_SESSION_KEY);
            if(!code.equals(kaptcha)){
                return new Result().failure(404,"验证码错误");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Result result = new Result();
        try {
            //将前端密码解密
            Object privateKey = ShiroUtils.getSession().getAttribute(Constant.PRIVATE_KEY);
            if (null == privateKey) {
                return new Result().failure(404,"请刷新后重新登陆");
            }
            byte[] passwords = RASUtils.decrypt((RSAPrivateKey) privateKey, RASUtils.hexStringToBytes(password));
            //还原密码
            password = new String(passwords).trim();
            Subject subject = ShiroUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(userName,password);
            subject.login(token);

            Map<String,Object> map = new HashMap<>();
            TabUserVo userVo = ShiroUtils.getUserEntity();
            if((userVo.getAduitType()&2) == 0){
                return new Result().failure(404,"该用户没有访问权限");
            }
            userVo.setPassword(null);
            userVo.setSalt(null);
            map.put("userVo",userVo);
            TabMapservice tabMap = tabMapService.getByUserId(userVo.getId());
            map.put("tabMap",tabMap);
            result.setData(map);
            //session验证码和秘钥移除
            ShiroUtils.getSession().removeAttribute(Constants.KAPTCHA_SESSION_KEY);
            ShiroUtils.getSession().removeAttribute(Constant.PRIVATE_KEY);
            //保存日志
            TabLoginLog log = new TabLoginLog();
            log.setLoginDate(new Date());
            log.setPlatType(0l);
            log.setUsername(userName);
            tabLoginService.insert(log);
            TabUser tabUser = (TabUser) ShiroUtils.getSubject().getPrincipal();
            LoginService.login(request,tabUser.getId().toString(),userName);
        }catch (UnknownAccountException e) {
            return result.failure(-1,e.getMessage());
        }catch (IncorrectCredentialsException e) {
            return result.failure(-1,"账号或密码不正确");
        }catch (LockedAccountException e) {
            return result.failure(-1,"账号已被禁用,请联系管理员");
        }catch (AuthenticationException e) {
            return result.failure(-1,e.getMessage());
        }catch (Exception e){
            return result.failure(-1,e.getMessage());
        }
        return result;
    }
    /**
     * 退出
     */
    @GetMapping("logout")
    @ApiOperation(value = "退出", notes = "退出")
    public Result logout(HttpServletRequest request) {
        ShiroUtils.logout();
        LoginService.loginOut(request);
        return new Result().success();
    }

    @ApiOperation("获取公钥和私钥")
    @GetMapping("getKey")
    public Result getKey() {
        HashMap<Object, Object> hashMap = new HashMap<>();
        RSAPublicKey rsapPublicKey = null;
        RSAPrivateKey rsaPrivateKey = null;
        try {
            KeyPair publicKey = RASUtils.generateKeyPair();
            rsapPublicKey = (RSAPublicKey) publicKey.getPublic();
            rsaPrivateKey = (RSAPrivateKey) publicKey.getPrivate();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //保存到shiro session
        ShiroUtils.setSessionAttribute(Constant.PRIVATE_KEY, rsaPrivateKey);
        hashMap.put("publicKey", rsapPublicKey.getModulus().toString(16));
        return new Result().success(hashMap);
    }
}
